package com.xy.auth.config;

import com.xy.auth.properties.JwtCAProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;

import java.security.KeyPair;
import java.util.Arrays;


//@Configuration
public class AuthServerUserInMemoryConfig extends AuthorizationServerConfigurerAdapter {

    private static final String CLIENT_ID = "client";
    private static final String SECRET_CHAR_SEQUENCE = "123123123";
    private static final String ALL = "all";
    private static final int ACCESS_TOKEN_VALIDITY_SECONDS = 30 * 60;
    // 密码模式授权模式
    private static final String GRANT_TYPE_PASSWORD = "password";
    //授权码模式
    private static final String AUTHORIZATION_CODE = "authorization_code";
    //简化授权模式
    private static final String IMPLICIT = "implicit";
    //客户端模式
    private static final String CLIENT_CREDENTIALS = "client_credentials";

    @Autowired
    private JwtCAProperties jwtCAProperties;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;


    //token存在那（像clientid clientsecret redirect url等，这些属性 肯定要存在数据库或存在jwt中）
    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(new InMemoryTokenStore()).authenticationManager(authenticationManager)
                //refersh token是不是 只能用一次
                .reuseRefreshTokens(Boolean.FALSE)
                .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); //支持GET,POST请求
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        //允许表单认证
        security.allowFormAuthenticationForClients();
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        /**
         *授权码模式
         * 请求code:第一步 需要请求下面路径获取code 只需要clientid 和 类型 拿code 并让用户授权
         *http://localhost:8900/oauth/authorize?response_type=code&client_id=client&redirect_uri=http://www.baidu.com&scope=all 或者
         *http://localhost:8900/oauth/authorize?response_type=code&client_id=client
         * 然后使用 localhost:8900/oauth/token post请求 body 体是 code=上一步请求的 和 grant_type=authorization_code
         * 并带上请求头：key 为 Authorization  值 为 (clientid ,client_secret  ==> clientid:client_secret  并对这个字符串进行base64编码 然后在 编码的前面加上"Basic ")
         *      如果是http头 可以使用HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); headers.setBasicAuth(CLIENT_ID,CLIENT_SECRET);
         * 并发到地址：localhost:8900/oauth/token 去获取token
         *
         * 最后拿着得到的token去请求资源路径：localhost:8900/auth/test 同时带上头：key 为Authorization 值为 “bearer +上一步获取的token”
         *
         *
         * implicit: 简化模式 不用用户输入用户名密码 直接拿code
         *http://localhost:8900/oauth/authorize?client_id=client&response_type=token&scope=all&redirect_uri=http://www.baidu.com
         *
         * password模式 直接通过 用户名密码 clientid client secret获取token 不用拿code（授权）
         *  http://localhost:8900/oauth/token?username=fox&password=123456&grant_type=password&client_id=client&client_secret=123123&scope=all
         *
         *  客户端模式   不需要拿code  直接拿着clientid 和clientsecret 获取token 不用拿code（授权）
         *  http://localhost:8900/oauth/token?grant_type=client_credentials&scope=all&client_id=client&client_secret=123123123
         *
         *  刷新令牌
         *  http://localhost:8900/oauth/token?grant_type=refresh_token&client_id=client&client_secret=123123&refresh_token=[refresh_token值]
         */

        clients.inMemory()
                //配置client_id
                .withClient(CLIENT_ID)
                //配置client-secret
                .secret(passwordEncoder.encode(SECRET_CHAR_SEQUENCE))
                //配置访问token的有效期
                .accessTokenValiditySeconds(3600)
                //配置刷新token的有效期
                .refreshTokenValiditySeconds(864000)
                //配置redirect_uri，用于授权成功后跳转
                .redirectUris("http://www.baidu.com")
                //配置申请的权限范围
                .scopes("all")
                //配置grant_type，表示授权类型
                /**
                 * 配置grant_type，表示授权类型
                 * authorization_code: 授权码模式
                 * implicit: 简化模式
                 * password： 密码模式
                 * client_credentials: 客户端模式
                 * refresh_token: 更新令牌
                 */
                .authorizedGrantTypes(AUTHORIZATION_CODE, GRANT_TYPE_PASSWORD, IMPLICIT, CLIENT_CREDENTIALS, "refresh_token");
    }
}
